package models.crawlers;

import models.crawlers.common.*;
import models.entities.ProductEntity;
import models.helpers.StringHelper;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class Invask extends ShopCrawler {
    private List<String> brandNames = new ArrayList<String>();
    private models.crawlers.common.DocumentCache documentCache;

    public Invask() {
        crawlerMainUrl = "http://invask.ru";
    }

    @Override
    protected WebSiteInfo initializeWebSiteInfo() throws IOException {
        SitePathInfo categoryPath = new SitePathInfo();
        categoryPath.url = crawlerMainUrl + "/cat";
        categoryPath.title = "INVASK";
        return new WebSiteInfo(categoryPath, 358, 6322);
    }

    @Override
    public List<CategoryInfo> getCategories(String url) throws IOException {
        List<CategoryInfo> categories = new ArrayList<CategoryInfo>();
        Document categoryPage = downloadPage(url);
        Elements childElements = categoryPage.select(".box-kategory.brand-category-box li a");
        for (Element element : childElements) {
            String childCategoryTitle = element.text().trim();
            String childCategoryUrl = getSourceUrl(element.attr("href"));
            CategoryInfo categoryInfo = new CategoryInfo(childCategoryTitle, childCategoryUrl);
            categories.add(categoryInfo);
        }
        return categories;
    }

    @Override
    public List<ProductInfo> getProducts(String url, int pageNumber) throws IOException {
        if (pageNumber > 1)
            url = getProductListPageUrl(url, pageNumber);
        Document categoryPage = downloadPage(url);
        brandNames = getBrandNames(categoryPage);
        Elements products = categoryPage.select(".kletka-2 ul li div.novinki-content");
        List<ProductInfo> productInfos = new ArrayList<ProductInfo>();
        for (Element productElement : products) {
            ProductInfo productInfo = new ProductInfo();
            Elements productAnchorElement = productElement.select("h3 a");
            productInfo.title = productAnchorElement.text().trim();
            productInfo.url = getSourceUrl(productAnchorElement.attr("href"));
            productInfos.add(productInfo);
        }
        return productInfos;
    }

    private List<String> getBrandNames(Document categoryPage) {
        Elements brandElements = categoryPage.select(".proizvoditel li a");
        List<String> brands = new ArrayList<String>();
        for (Element element : brandElements) {
            brands.add(element.text());
        }
        return brands;
    }

    @Override
    public ProductEntity getProduct(String url) throws Exception {
        try {
            Document productPage = downloadPage(url);
            ProductEntity productEntity = new ProductEntity();
            Elements description = productPage.select(".kratkoe-opisanie .mid-block #txt");
            Elements priceElements = productPage.select(".vkorzinu .cena .new-cena span");
            Elements nameElements = productPage.select(".novinki-content h3");
            Elements shortDescElements = productPage.select(".opisanie-right p");

            if (shortDescElements.size() > 0)
                productEntity.shortDescription = shortDescElements.text().trim();
            if (nameElements.size() > 0)
                productEntity.title = nameElements.text().trim();
            if (priceElements.size() > 1) {

                Element roznPrice = priceElements.get(1);
                String priceText = roznPrice.text().trim().replace("&nbsp;", "").replace(String.valueOf(Character.toChars(160)), "");
                if (StringHelper.isNumeric(priceText)) {
                    productEntity.price = Integer.parseInt(priceText);
                }
            }
            if (description.select(".notice").size() == 0)
                productEntity.description = description.html();
            productEntity.brandName = getBrandName(productEntity.title);
            //productEntity.brandImageUrl = getBrandImageUrl(productPage);
            addPictures(productEntity, productPage);
            return productEntity;
        } catch (Exception ex) {
            throw new ProductParsingException(ex);
        }
    }

    private void addPictures(ProductEntity productEntity, Document productPage) throws Exception {
        Elements pictures = productPage.select(".mid-block .novinki-content ul li a");
        if (pictures.size() > 0) {
            for (Element picture : pictures) {
                String pictureUrl = String.format("%1$s%2$s", crawlerMainUrl, picture.attr("href"));
                productEntity.pictureUrls.add(pictureUrl);
            }
        }
    }

    private String getBrandName(String title) {
        for (String brandName : brandNames) {
            if (title.contains(brandName)) {
                return brandName;
            }
        }
        return "";
    }

    @Override
    protected String getProductSourceId(String url) {
        return url.substring(url.lastIndexOf("/") + 1);
    }

    @Override
    protected Integer findNextPage(Integer pageNumber, String url) throws IOException {
        Document productList;
        if (documentCache != null) {
            String url1 = getProductListPageUrl(url, pageNumber);
            if (documentCache.cacheUrl.equals(url1))
                productList = documentCache.document;
            else
                productList = downloadPage(url1);
        } else {
            String url1 = getProductListPageUrl(url, pageNumber);
            productList = downloadPage(url1);
        }
        Elements pager = productList.select(".page-link");
        if (pager.size() == 0) {
            return null;
        } else {
            int nextPageNumber = pageNumber+1;
            String nextPageText = String.format(">%1$s</a>", nextPageNumber);
            if (pager.html().contains(nextPageText)) {
                return nextPageNumber;
            } else {
                return null;
            }
        }
    }

    private String getProductListPageUrl(String url, int pageNumber) {
        return String.format("%1$s/0/%2$s", url, pageNumber);
    }

    @Override
    protected int getCategoryProductsCount(String url) throws IOException {
        Document productPage = downloadPage(url + "/0/10000");
        Elements pager = productPage.select(".page-link a");
        Elements products = productPage.select(".kletka-2 ul li div.novinki-content");
        if (pager.size() > 0) {
            Element pageElement = pager.last();
            int lastPageNumber = Integer.parseInt(pageElement.text().trim());
            int totalCount = (12 * lastPageNumber) + products.size();
            return totalCount;
        }
        return products.size();
    }
}
